"OSTree.AsyncProgress",
"OSTree.BootconfigParser",
"OSTree.ChecksumFlags",
+ "OSTree.CommitSizesEntry",
"OSTree.Deployment",
"OSTree.DeploymentUnlockedState",
"OSTree.DiffFlags",
--- /dev/null
+// This file was generated by gir (https://github.com/gtk-rs/gir)
+// from gir-files (https://github.com/gtk-rs/gir-files)
+// DO NOT EDIT
+
+#[cfg(any(feature = "v2020_1", feature = "dox"))]
+use glib::translate::*;
+use ostree_sys;
+#[cfg(any(feature = "v2020_1", feature = "dox"))]
+use ObjectType;
+
+glib_wrapper! {
+ #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
+ pub struct CommitSizesEntry(Boxed<ostree_sys::OstreeCommitSizesEntry>);
+
+ match fn {
+ copy => |ptr| ostree_sys::ostree_commit_sizes_entry_copy(mut_override(ptr)),
+ free => |ptr| ostree_sys::ostree_commit_sizes_entry_free(ptr),
+ get_type => || ostree_sys::ostree_commit_sizes_entry_get_type(),
+ }
+}
+
+impl CommitSizesEntry {
+ #[cfg(any(feature = "v2020_1", feature = "dox"))]
+ pub fn new(checksum: &str, objtype: ObjectType, unpacked: u64, archived: u64) -> Option<CommitSizesEntry> {
+ unsafe {
+ from_glib_full(ostree_sys::ostree_commit_sizes_entry_new(checksum.to_glib_none().0, objtype.to_glib(), unpacked, archived))
+ }
+ }
+}
use ostree_sys;
use std::mem;
use std::ptr;
+#[cfg(any(feature = "v2020_1", feature = "dox"))]
+use CommitSizesEntry;
use DiffFlags;
use DiffItem;
use ObjectType;
}
}
-//#[cfg(any(feature = "v2020_1", feature = "dox"))]
-//pub fn commit_get_object_sizes(commit_variant: &glib::Variant, out_sizes_entries: /*Ignored*/Vec<CommitSizesEntry>) -> Result<(), glib::Error> {
-// unsafe { TODO: call ostree_sys:ostree_commit_get_object_sizes() }
-//}
+#[cfg(any(feature = "v2020_1", feature = "dox"))]
+pub fn commit_get_object_sizes(commit_variant: &glib::Variant) -> Result<Vec<CommitSizesEntry>, glib::Error> {
+ unsafe {
+ let mut out_sizes_entries = ptr::null_mut();
+ let mut error = ptr::null_mut();
+ let _ = ostree_sys::ostree_commit_get_object_sizes(commit_variant.to_glib_none().0, &mut out_sizes_entries, &mut error);
+ if error.is_null() { Ok(FromGlibPtrContainer::from_glib_container(out_sizes_entries)) } else { Err(from_glib_full(error)) }
+ }
+}
pub fn commit_get_parent(commit_variant: &glib::Variant) -> Option<GString> {
unsafe {
#[cfg(any(feature = "v2018_6", feature = "dox"))]
pub use self::collection_ref::CollectionRef;
+#[cfg(any(feature = "v2020_1", feature = "dox"))]
+mod commit_sizes_entry;
+#[cfg(any(feature = "v2020_1", feature = "dox"))]
+pub use self::commit_sizes_entry::CommitSizesEntry;
+
mod diff_item;
pub use self::diff_item::DiffItem;
Generated by gir (https://github.com/gtk-rs/gir @ 2d1ffab1)
-from gir-files (https://github.com/gtk-rs/gir-files @ eec42a9)
+from gir-files (https://github.com/gtk-rs/gir-files @ ff904f0)
-use glib::translate::{from_glib_full, FromGlibPtrFull};
-use glib::GString;
+use glib::{
+ translate::{from_glib_full, FromGlibPtrFull, FromGlibPtrNone},
+ GString,
+};
use glib_sys::{g_free, g_malloc, g_malloc0, gpointer};
use libc::c_char;
-use std::fmt;
-use std::ptr::copy_nonoverlapping;
+use std::{fmt, ptr::copy_nonoverlapping};
const BYTES_LEN: usize = ostree_sys::OSTREE_SHA256_DIGEST_LEN as usize;
const HEX_LEN: usize = ostree_sys::OSTREE_SHA256_STRING_LEN as usize;
}
impl Checksum {
+ pub const DIGEST_LEN: usize = BYTES_LEN;
+
/// Create a `Checksum` value, taking ownership of the given memory location.
///
/// # Safety
/// `g_free` (this is e.g. the case if the memory was allocated with `g_malloc`). The value
/// takes ownership of the memory, i.e. the memory is freed when the value is dropped. The
/// memory must not be freed by other code.
- unsafe fn new(bytes: *mut [u8; BYTES_LEN]) -> Checksum {
+ unsafe fn new(bytes: *mut [u8; Self::DIGEST_LEN]) -> Checksum {
assert!(!bytes.is_null());
Checksum { bytes }
}
+ /// Create a `Checksum` from a byte array.
+ pub fn from_bytes(checksum: &[u8; Self::DIGEST_LEN]) -> Checksum {
+ let ptr = checksum as *const [u8; BYTES_LEN] as *mut [u8; BYTES_LEN];
+ unsafe {
+ // Safety: we know this byte array is long enough.
+ Checksum::from_glib_none(ptr)
+ }
+ }
+
/// Create a `Checksum` from a hexadecimal SHA256 string.
///
/// Unfortunately, the underlying libostree function has no way to report parsing errors. If the
impl Clone for Checksum {
fn clone(&self) -> Self {
- unsafe {
- let cloned = g_malloc(BYTES_LEN) as *mut [u8; BYTES_LEN];
- // copy one array of 32 elements
- copy_nonoverlapping::<[u8; BYTES_LEN]>(self.bytes, cloned, 1);
- Checksum::new(cloned)
- }
+ unsafe { Checksum::from_glib_none(self.bytes) }
}
}
}
}
+impl FromGlibPtrNone<*mut [u8; BYTES_LEN]> for Checksum {
+ unsafe fn from_glib_none(ptr: *mut [u8; BYTES_LEN]) -> Self {
+ let cloned = g_malloc(BYTES_LEN) as *mut [u8; BYTES_LEN];
+ // copy one array of 32 elements
+ copy_nonoverlapping::<[u8; BYTES_LEN]>(ptr, cloned, 1);
+ Checksum::new(cloned)
+ }
+}
+
#[cfg(test)]
mod tests {
use super::*;
assert_eq!(checksum.to_string(), "00".repeat(BYTES_LEN));
}
+ #[test]
+ fn should_create_checksum_from_bytes_copy() {
+ let bytes = [0u8; BYTES_LEN];
+ let checksum = Checksum::from_bytes(&bytes);
+ assert_eq!(checksum.to_string(), "00".repeat(BYTES_LEN));
+ }
+
#[test]
fn should_parse_checksum_string_to_bytes() {
let csum = Checksum::from_hex(CHECKSUM_STRING);
--- /dev/null
+use crate::{auto::CommitSizesEntry, auto::ObjectType};
+use glib::{
+ translate::{FromGlib, FromGlibPtrNone, ToGlibPtr},
+ GString,
+};
+
+impl CommitSizesEntry {
+ /// Object checksum as hex string.
+ pub fn checksum(&self) -> GString {
+ let underlying = self.to_glib_none();
+ unsafe { GString::from_glib_none((*underlying.0).checksum) }
+ }
+
+ /// The object type.
+ pub fn objtype(&self) -> ObjectType {
+ let underlying = self.to_glib_none();
+ unsafe { ObjectType::from_glib((*underlying.0).objtype) }
+ }
+
+ /// Unpacked object size.
+ pub fn unpacked(&self) -> u64 {
+ let underlying = self.to_glib_none();
+ unsafe { (*underlying.0).unpacked }
+ }
+
+ /// Compressed object size.
+ pub fn archived(&self) -> u64 {
+ let underlying = self.to_glib_none();
+ unsafe { (*underlying.0).archived }
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ const CHECKSUM_STRING: &str =
+ "bf875306783efdc5bcab37ea10b6ca4e9b6aea8b94580d0ca94af120565c0e8a";
+
+ #[test]
+ fn should_get_values_from_commit_sizes_entry() {
+ let entry = CommitSizesEntry::new(CHECKSUM_STRING, ObjectType::Commit, 15, 16).unwrap();
+ assert_eq!(entry.checksum(), CHECKSUM_STRING);
+ assert_eq!(entry.objtype(), ObjectType::Commit);
+ assert_eq!(entry.unpacked(), 15);
+ assert_eq!(entry.archived(), 16);
+ }
+}
// handwritten code
mod checksum;
pub use crate::checksum::*;
-
#[cfg(any(feature = "v2018_6", feature = "dox"))]
mod collection_ref;
#[cfg(any(feature = "v2018_6", feature = "dox"))]
pub use crate::collection_ref::*;
-
mod functions;
pub use crate::functions::*;
-
#[cfg(any(feature = "v2019_3", feature = "dox"))]
mod kernel_args;
#[cfg(any(feature = "v2019_3", feature = "dox"))]
pub use crate::kernel_args::*;
-
mod object_name;
pub use crate::object_name::*;
-
mod repo;
pub use crate::repo::*;
-
#[cfg(any(feature = "v2016_8", feature = "dox"))]
mod repo_checkout_at_options;
#[cfg(any(feature = "v2016_8", feature = "dox"))]
pub use crate::repo_checkout_at_options::*;
-
mod se_policy;
pub use crate::se_policy::*;
+#[cfg(any(feature = "v2020_1", feature = "dox"))]
+mod commit_sizes_entry;
+#[cfg(any(feature = "v2020_1", feature = "dox"))]
+pub use crate::commit_sizes_entry::*;
// tests
#[cfg(test)]
+++ /dev/null
-use crate::{RepoCheckoutMode, RepoCheckoutOverwriteMode, RepoDevInoCache, SePolicy};
-use glib::translate::*;
-use libc::c_char;
-use ostree_sys::*;
-use std::path::PathBuf;
-
-#[cfg(any(feature = "v2018_2", feature = "dox"))]
-mod repo_checkout_filter;
-#[cfg(any(feature = "v2018_2", feature = "dox"))]
-pub use self::repo_checkout_filter::RepoCheckoutFilter;
-
-pub struct RepoCheckoutAtOptions {
- pub mode: RepoCheckoutMode,
- pub overwrite_mode: RepoCheckoutOverwriteMode,
- pub enable_uncompressed_cache: bool,
- pub enable_fsync: bool,
- pub process_whiteouts: bool,
- pub no_copy_fallback: bool,
- #[cfg(any(feature = "v2017_6", feature = "dox"))]
- pub force_copy: bool,
- #[cfg(any(feature = "v2017_7", feature = "dox"))]
- pub bareuseronly_dirs: bool,
- #[cfg(any(feature = "v2018_9", feature = "dox"))]
- pub force_copy_zerosized: bool,
- pub subpath: Option<PathBuf>,
- pub devino_to_csum_cache: Option<RepoDevInoCache>,
- /// A callback function to decide which files and directories will be checked out from the
- /// repo. See the documentation on [RepoCheckoutFilter](struct.RepoCheckoutFilter.html) for more
- /// information on the signature.
- ///
- /// # Panics
- /// This callback may not panic. If it does, `abort()` will be called to avoid unwinding across
- /// an FFI boundary and into the libostree C code (which is Undefined Behavior). If you prefer to
- /// swallow the panic rather than aborting, you can use `std::panic::catch_unwind` inside your
- /// callback to catch and silence any panics that occur.
- #[cfg(any(feature = "v2018_2", feature = "dox"))]
- pub filter: Option<RepoCheckoutFilter>,
- #[cfg(any(feature = "v2017_6", feature = "dox"))]
- pub sepolicy: Option<SePolicy>,
- pub sepolicy_prefix: Option<String>,
-}
-
-impl Default for RepoCheckoutAtOptions {
- fn default() -> Self {
- RepoCheckoutAtOptions {
- mode: RepoCheckoutMode::None,
- overwrite_mode: RepoCheckoutOverwriteMode::None,
- enable_uncompressed_cache: false,
- enable_fsync: false,
- process_whiteouts: false,
- no_copy_fallback: false,
- #[cfg(feature = "v2017_6")]
- force_copy: false,
- #[cfg(feature = "v2017_7")]
- bareuseronly_dirs: false,
- #[cfg(feature = "v2018_9")]
- force_copy_zerosized: false,
- subpath: None,
- devino_to_csum_cache: None,
- #[cfg(feature = "v2018_2")]
- filter: None,
- #[cfg(feature = "v2017_6")]
- sepolicy: None,
- sepolicy_prefix: None,
- }
- }
-}
-
-type StringStash<'a, T> = Stash<'a, *const c_char, Option<T>>;
-type WrapperStash<'a, GlibT, WrappedT> = Stash<'a, *mut GlibT, Option<WrappedT>>;
-
-impl<'a> ToGlibPtr<'a, *const OstreeRepoCheckoutAtOptions> for RepoCheckoutAtOptions {
- #[allow(clippy::type_complexity)]
- type Storage = (
- Box<OstreeRepoCheckoutAtOptions>,
- StringStash<'a, PathBuf>,
- StringStash<'a, String>,
- WrapperStash<'a, OstreeRepoDevInoCache, RepoDevInoCache>,
- WrapperStash<'a, OstreeSePolicy, SePolicy>,
- );
-
- // We need to make sure that all memory pointed to by the returned pointer is kept alive by
- // either the `self` reference or the returned Stash.
- fn to_glib_none(&'a self) -> Stash<*const OstreeRepoCheckoutAtOptions, Self> {
- // Creating this struct from zeroed memory is fine since it's `repr(C)` and only contains
- // primitive types. In fact, the libostree docs say to zero the struct. This means we handle
- // the unused bytes correctly.
- // The struct needs to be boxed so the pointer we return remains valid even as the Stash is
- // moved around.
- let mut options = Box::new(unsafe { std::mem::zeroed::<OstreeRepoCheckoutAtOptions>() });
- options.mode = self.mode.to_glib();
- options.overwrite_mode = self.overwrite_mode.to_glib();
- options.enable_uncompressed_cache = self.enable_uncompressed_cache.to_glib();
- options.enable_fsync = self.enable_fsync.to_glib();
- options.process_whiteouts = self.process_whiteouts.to_glib();
- options.no_copy_fallback = self.no_copy_fallback.to_glib();
-
- #[cfg(feature = "v2017_6")]
- {
- options.force_copy = self.force_copy.to_glib();
- }
-
- #[cfg(feature = "v2017_7")]
- {
- options.bareuseronly_dirs = self.bareuseronly_dirs.to_glib();
- }
-
- #[cfg(feature = "v2018_9")]
- {
- options.force_copy_zerosized = self.force_copy_zerosized.to_glib();
- }
-
- // We keep these complex values alive by returning them in our Stash. Technically, some of
- // these are being kept alive by `self` already, but it's better to be consistent here.
- let subpath = self.subpath.to_glib_none();
- options.subpath = subpath.0;
- let sepolicy_prefix = self.sepolicy_prefix.to_glib_none();
- options.sepolicy_prefix = sepolicy_prefix.0;
- let devino_to_csum_cache = self.devino_to_csum_cache.to_glib_none();
- options.devino_to_csum_cache = devino_to_csum_cache.0;
-
- #[cfg(feature = "v2017_6")]
- let sepolicy = {
- let sepolicy = self.sepolicy.to_glib_none();
- options.sepolicy = sepolicy.0;
- sepolicy
- };
- #[cfg(not(feature = "v2017_6"))]
- let sepolicy = None.to_glib_none();
-
- #[cfg(feature = "v2018_2")]
- {
- if let Some(filter) = &self.filter {
- options.filter_user_data = filter.to_glib_none().0;
- options.filter = Some(repo_checkout_filter::filter_trampoline_unwindsafe);
- }
- }
-
- Stash(
- options.as_ref(),
- (
- options,
- subpath,
- sepolicy_prefix,
- devino_to_csum_cache,
- sepolicy,
- ),
- )
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use glib_sys::{GFALSE, GTRUE};
- use std::ffi::{CStr, CString};
- use std::ptr;
-
- #[test]
- fn should_convert_default_options() {
- let options = RepoCheckoutAtOptions::default();
- let stash = options.to_glib_none();
- let ptr = stash.0;
- unsafe {
- assert_eq!((*ptr).mode, OSTREE_REPO_CHECKOUT_MODE_NONE);
- assert_eq!((*ptr).overwrite_mode, OSTREE_REPO_CHECKOUT_OVERWRITE_NONE);
- assert_eq!((*ptr).enable_uncompressed_cache, GFALSE);
- assert_eq!((*ptr).enable_fsync, GFALSE);
- assert_eq!((*ptr).process_whiteouts, GFALSE);
- assert_eq!((*ptr).no_copy_fallback, GFALSE);
- #[cfg(feature = "v2017_6")]
- assert_eq!((*ptr).force_copy, GFALSE);
- #[cfg(feature = "v2017_7")]
- assert_eq!((*ptr).bareuseronly_dirs, GFALSE);
- #[cfg(feature = "v2018_9")]
- assert_eq!((*ptr).force_copy_zerosized, GFALSE);
- assert_eq!((*ptr).unused_bools, [GFALSE; 4]);
- assert_eq!((*ptr).subpath, ptr::null());
- assert_eq!((*ptr).devino_to_csum_cache, ptr::null_mut());
- assert_eq!((*ptr).unused_ints, [0; 6]);
- assert_eq!((*ptr).unused_ptrs, [ptr::null_mut(); 3]);
- #[cfg(feature = "v2018_2")]
- assert_eq!((*ptr).filter, None);
- #[cfg(feature = "v2018_2")]
- assert_eq!((*ptr).filter_user_data, ptr::null_mut());
- #[cfg(feature = "v2017_6")]
- assert_eq!((*ptr).sepolicy, ptr::null_mut());
- assert_eq!((*ptr).sepolicy_prefix, ptr::null());
- }
- }
-
- #[test]
- fn should_convert_non_default_options() {
- let options = RepoCheckoutAtOptions {
- mode: RepoCheckoutMode::User,
- overwrite_mode: RepoCheckoutOverwriteMode::UnionIdentical,
- enable_uncompressed_cache: true,
- enable_fsync: true,
- process_whiteouts: true,
- no_copy_fallback: true,
- #[cfg(feature = "v2017_6")]
- force_copy: true,
- #[cfg(feature = "v2017_7")]
- bareuseronly_dirs: true,
- #[cfg(feature = "v2018_9")]
- force_copy_zerosized: true,
- subpath: Some("sub/path".into()),
- devino_to_csum_cache: Some(RepoDevInoCache::new()),
- #[cfg(feature = "v2018_2")]
- filter: RepoCheckoutFilter::new(|_repo, _path, _stat| {
- crate::RepoCheckoutFilterResult::Skip
- }),
- #[cfg(feature = "v2017_6")]
- sepolicy: Some(
- SePolicy::new(&gio::File::new_for_path("a/b"), gio::NONE_CANCELLABLE).unwrap(),
- ),
- sepolicy_prefix: Some("prefix".into()),
- };
- let stash = options.to_glib_none();
- let ptr = stash.0;
- unsafe {
- assert_eq!((*ptr).mode, OSTREE_REPO_CHECKOUT_MODE_USER);
- assert_eq!(
- (*ptr).overwrite_mode,
- OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL
- );
- assert_eq!((*ptr).enable_uncompressed_cache, GTRUE);
- assert_eq!((*ptr).enable_fsync, GTRUE);
- assert_eq!((*ptr).process_whiteouts, GTRUE);
- assert_eq!((*ptr).no_copy_fallback, GTRUE);
- #[cfg(feature = "v2017_6")]
- assert_eq!((*ptr).force_copy, GTRUE);
- #[cfg(feature = "v2017_7")]
- assert_eq!((*ptr).bareuseronly_dirs, GTRUE);
- #[cfg(feature = "v2018_9")]
- assert_eq!((*ptr).force_copy_zerosized, GTRUE);
- assert_eq!((*ptr).unused_bools, [GFALSE; 4]);
- assert_eq!(
- CStr::from_ptr((*ptr).subpath),
- CString::new("sub/path").unwrap().as_c_str()
- );
- assert_eq!(
- (*ptr).devino_to_csum_cache,
- options.devino_to_csum_cache.to_glib_none().0
- );
- assert_eq!((*ptr).unused_ints, [0; 6]);
- assert_eq!((*ptr).unused_ptrs, [ptr::null_mut(); 3]);
- #[cfg(feature = "v2018_2")]
- assert!((*ptr).filter == Some(repo_checkout_filter::filter_trampoline_unwindsafe));
- #[cfg(feature = "v2018_2")]
- assert_eq!(
- (*ptr).filter_user_data,
- options.filter.as_ref().unwrap().to_glib_none().0,
- );
- #[cfg(feature = "v2017_6")]
- assert_eq!((*ptr).sepolicy, options.sepolicy.to_glib_none().0);
- assert_eq!(
- CStr::from_ptr((*ptr).sepolicy_prefix),
- CString::new("prefix").unwrap().as_c_str()
- );
- }
- }
-}
--- /dev/null
+use crate::{RepoCheckoutMode, RepoCheckoutOverwriteMode, RepoDevInoCache, SePolicy};
+use glib::translate::*;
+use libc::c_char;
+use ostree_sys::*;
+use std::path::PathBuf;
+
+#[cfg(any(feature = "v2018_2", feature = "dox"))]
+mod repo_checkout_filter;
+#[cfg(any(feature = "v2018_2", feature = "dox"))]
+pub use self::repo_checkout_filter::RepoCheckoutFilter;
+
+pub struct RepoCheckoutAtOptions {
+ pub mode: RepoCheckoutMode,
+ pub overwrite_mode: RepoCheckoutOverwriteMode,
+ pub enable_uncompressed_cache: bool,
+ pub enable_fsync: bool,
+ pub process_whiteouts: bool,
+ pub no_copy_fallback: bool,
+ #[cfg(any(feature = "v2017_6", feature = "dox"))]
+ pub force_copy: bool,
+ #[cfg(any(feature = "v2017_7", feature = "dox"))]
+ pub bareuseronly_dirs: bool,
+ #[cfg(any(feature = "v2018_9", feature = "dox"))]
+ pub force_copy_zerosized: bool,
+ pub subpath: Option<PathBuf>,
+ pub devino_to_csum_cache: Option<RepoDevInoCache>,
+ /// A callback function to decide which files and directories will be checked out from the
+ /// repo. See the documentation on [RepoCheckoutFilter](struct.RepoCheckoutFilter.html) for more
+ /// information on the signature.
+ ///
+ /// # Panics
+ /// This callback may not panic. If it does, `abort()` will be called to avoid unwinding across
+ /// an FFI boundary and into the libostree C code (which is Undefined Behavior). If you prefer to
+ /// swallow the panic rather than aborting, you can use `std::panic::catch_unwind` inside your
+ /// callback to catch and silence any panics that occur.
+ #[cfg(any(feature = "v2018_2", feature = "dox"))]
+ pub filter: Option<RepoCheckoutFilter>,
+ #[cfg(any(feature = "v2017_6", feature = "dox"))]
+ pub sepolicy: Option<SePolicy>,
+ pub sepolicy_prefix: Option<String>,
+}
+
+impl Default for RepoCheckoutAtOptions {
+ fn default() -> Self {
+ RepoCheckoutAtOptions {
+ mode: RepoCheckoutMode::None,
+ overwrite_mode: RepoCheckoutOverwriteMode::None,
+ enable_uncompressed_cache: false,
+ enable_fsync: false,
+ process_whiteouts: false,
+ no_copy_fallback: false,
+ #[cfg(feature = "v2017_6")]
+ force_copy: false,
+ #[cfg(feature = "v2017_7")]
+ bareuseronly_dirs: false,
+ #[cfg(feature = "v2018_9")]
+ force_copy_zerosized: false,
+ subpath: None,
+ devino_to_csum_cache: None,
+ #[cfg(feature = "v2018_2")]
+ filter: None,
+ #[cfg(feature = "v2017_6")]
+ sepolicy: None,
+ sepolicy_prefix: None,
+ }
+ }
+}
+
+type StringStash<'a, T> = Stash<'a, *const c_char, Option<T>>;
+type WrapperStash<'a, GlibT, WrappedT> = Stash<'a, *mut GlibT, Option<WrappedT>>;
+
+impl<'a> ToGlibPtr<'a, *const OstreeRepoCheckoutAtOptions> for RepoCheckoutAtOptions {
+ #[allow(clippy::type_complexity)]
+ type Storage = (
+ Box<OstreeRepoCheckoutAtOptions>,
+ StringStash<'a, PathBuf>,
+ StringStash<'a, String>,
+ WrapperStash<'a, OstreeRepoDevInoCache, RepoDevInoCache>,
+ WrapperStash<'a, OstreeSePolicy, SePolicy>,
+ );
+
+ // We need to make sure that all memory pointed to by the returned pointer is kept alive by
+ // either the `self` reference or the returned Stash.
+ fn to_glib_none(&'a self) -> Stash<*const OstreeRepoCheckoutAtOptions, Self> {
+ // Creating this struct from zeroed memory is fine since it's `repr(C)` and only contains
+ // primitive types. In fact, the libostree docs say to zero the struct. This means we handle
+ // the unused bytes correctly.
+ // The struct needs to be boxed so the pointer we return remains valid even as the Stash is
+ // moved around.
+ let mut options = Box::new(unsafe { std::mem::zeroed::<OstreeRepoCheckoutAtOptions>() });
+ options.mode = self.mode.to_glib();
+ options.overwrite_mode = self.overwrite_mode.to_glib();
+ options.enable_uncompressed_cache = self.enable_uncompressed_cache.to_glib();
+ options.enable_fsync = self.enable_fsync.to_glib();
+ options.process_whiteouts = self.process_whiteouts.to_glib();
+ options.no_copy_fallback = self.no_copy_fallback.to_glib();
+
+ #[cfg(feature = "v2017_6")]
+ {
+ options.force_copy = self.force_copy.to_glib();
+ }
+
+ #[cfg(feature = "v2017_7")]
+ {
+ options.bareuseronly_dirs = self.bareuseronly_dirs.to_glib();
+ }
+
+ #[cfg(feature = "v2018_9")]
+ {
+ options.force_copy_zerosized = self.force_copy_zerosized.to_glib();
+ }
+
+ // We keep these complex values alive by returning them in our Stash. Technically, some of
+ // these are being kept alive by `self` already, but it's better to be consistent here.
+ let subpath = self.subpath.to_glib_none();
+ options.subpath = subpath.0;
+ let sepolicy_prefix = self.sepolicy_prefix.to_glib_none();
+ options.sepolicy_prefix = sepolicy_prefix.0;
+ let devino_to_csum_cache = self.devino_to_csum_cache.to_glib_none();
+ options.devino_to_csum_cache = devino_to_csum_cache.0;
+
+ #[cfg(feature = "v2017_6")]
+ let sepolicy = {
+ let sepolicy = self.sepolicy.to_glib_none();
+ options.sepolicy = sepolicy.0;
+ sepolicy
+ };
+ #[cfg(not(feature = "v2017_6"))]
+ let sepolicy = None.to_glib_none();
+
+ #[cfg(feature = "v2018_2")]
+ {
+ if let Some(filter) = &self.filter {
+ options.filter_user_data = filter.to_glib_none().0;
+ options.filter = Some(repo_checkout_filter::filter_trampoline_unwindsafe);
+ }
+ }
+
+ Stash(
+ options.as_ref(),
+ (
+ options,
+ subpath,
+ sepolicy_prefix,
+ devino_to_csum_cache,
+ sepolicy,
+ ),
+ )
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use glib_sys::{GFALSE, GTRUE};
+ use std::ffi::{CStr, CString};
+ use std::ptr;
+
+ #[test]
+ fn should_convert_default_options() {
+ let options = RepoCheckoutAtOptions::default();
+ let stash = options.to_glib_none();
+ let ptr = stash.0;
+ unsafe {
+ assert_eq!((*ptr).mode, OSTREE_REPO_CHECKOUT_MODE_NONE);
+ assert_eq!((*ptr).overwrite_mode, OSTREE_REPO_CHECKOUT_OVERWRITE_NONE);
+ assert_eq!((*ptr).enable_uncompressed_cache, GFALSE);
+ assert_eq!((*ptr).enable_fsync, GFALSE);
+ assert_eq!((*ptr).process_whiteouts, GFALSE);
+ assert_eq!((*ptr).no_copy_fallback, GFALSE);
+ #[cfg(feature = "v2017_6")]
+ assert_eq!((*ptr).force_copy, GFALSE);
+ #[cfg(feature = "v2017_7")]
+ assert_eq!((*ptr).bareuseronly_dirs, GFALSE);
+ #[cfg(feature = "v2018_9")]
+ assert_eq!((*ptr).force_copy_zerosized, GFALSE);
+ assert_eq!((*ptr).unused_bools, [GFALSE; 4]);
+ assert_eq!((*ptr).subpath, ptr::null());
+ assert_eq!((*ptr).devino_to_csum_cache, ptr::null_mut());
+ assert_eq!((*ptr).unused_ints, [0; 6]);
+ assert_eq!((*ptr).unused_ptrs, [ptr::null_mut(); 3]);
+ #[cfg(feature = "v2018_2")]
+ assert_eq!((*ptr).filter, None);
+ #[cfg(feature = "v2018_2")]
+ assert_eq!((*ptr).filter_user_data, ptr::null_mut());
+ #[cfg(feature = "v2017_6")]
+ assert_eq!((*ptr).sepolicy, ptr::null_mut());
+ assert_eq!((*ptr).sepolicy_prefix, ptr::null());
+ }
+ }
+
+ #[test]
+ fn should_convert_non_default_options() {
+ let options = RepoCheckoutAtOptions {
+ mode: RepoCheckoutMode::User,
+ overwrite_mode: RepoCheckoutOverwriteMode::UnionIdentical,
+ enable_uncompressed_cache: true,
+ enable_fsync: true,
+ process_whiteouts: true,
+ no_copy_fallback: true,
+ #[cfg(feature = "v2017_6")]
+ force_copy: true,
+ #[cfg(feature = "v2017_7")]
+ bareuseronly_dirs: true,
+ #[cfg(feature = "v2018_9")]
+ force_copy_zerosized: true,
+ subpath: Some("sub/path".into()),
+ devino_to_csum_cache: Some(RepoDevInoCache::new()),
+ #[cfg(feature = "v2018_2")]
+ filter: RepoCheckoutFilter::new(|_repo, _path, _stat| {
+ crate::RepoCheckoutFilterResult::Skip
+ }),
+ #[cfg(feature = "v2017_6")]
+ sepolicy: Some(
+ SePolicy::new(&gio::File::new_for_path("a/b"), gio::NONE_CANCELLABLE).unwrap(),
+ ),
+ sepolicy_prefix: Some("prefix".into()),
+ };
+ let stash = options.to_glib_none();
+ let ptr = stash.0;
+ unsafe {
+ assert_eq!((*ptr).mode, OSTREE_REPO_CHECKOUT_MODE_USER);
+ assert_eq!(
+ (*ptr).overwrite_mode,
+ OSTREE_REPO_CHECKOUT_OVERWRITE_UNION_IDENTICAL
+ );
+ assert_eq!((*ptr).enable_uncompressed_cache, GTRUE);
+ assert_eq!((*ptr).enable_fsync, GTRUE);
+ assert_eq!((*ptr).process_whiteouts, GTRUE);
+ assert_eq!((*ptr).no_copy_fallback, GTRUE);
+ #[cfg(feature = "v2017_6")]
+ assert_eq!((*ptr).force_copy, GTRUE);
+ #[cfg(feature = "v2017_7")]
+ assert_eq!((*ptr).bareuseronly_dirs, GTRUE);
+ #[cfg(feature = "v2018_9")]
+ assert_eq!((*ptr).force_copy_zerosized, GTRUE);
+ assert_eq!((*ptr).unused_bools, [GFALSE; 4]);
+ assert_eq!(
+ CStr::from_ptr((*ptr).subpath),
+ CString::new("sub/path").unwrap().as_c_str()
+ );
+ assert_eq!(
+ (*ptr).devino_to_csum_cache,
+ options.devino_to_csum_cache.to_glib_none().0
+ );
+ assert_eq!((*ptr).unused_ints, [0; 6]);
+ assert_eq!((*ptr).unused_ptrs, [ptr::null_mut(); 3]);
+ #[cfg(feature = "v2018_2")]
+ assert!((*ptr).filter == Some(repo_checkout_filter::filter_trampoline_unwindsafe));
+ #[cfg(feature = "v2018_2")]
+ assert_eq!(
+ (*ptr).filter_user_data,
+ options.filter.as_ref().unwrap().to_glib_none().0,
+ );
+ #[cfg(feature = "v2017_6")]
+ assert_eq!((*ptr).sepolicy, options.sepolicy.to_glib_none().0);
+ assert_eq!(
+ CStr::from_ptr((*ptr).sepolicy_prefix),
+ CString::new("prefix").unwrap().as_c_str()
+ );
+ }
+ }
+}
Generated by gir (https://github.com/gtk-rs/gir @ 2d1ffab1)
-from gir-files (https://github.com/gtk-rs/gir-files @ eec42a9)
+from gir-files (https://github.com/gtk-rs/gir-files @ ff904f0)